﻿/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/

using System;

namespace CSharpKit.Numerics.LinearAlgebra.Factorization
{
    /// <summary>
    /// 乔里斯基(Cholesky)分解 <br/>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <remarks>
    /// 定义：把一个对称正定的矩阵表示成一个下三角矩阵L和其转置的乘积的分解 <para/>
    /// 如果矩阵A为n阶对称正定矩阵（symmetric, positive definite matrix A），则存在一个
    /// 对角元素为正数的下三角实矩阵L，使得 A = L*L^T，其中，L称为Cholesky因子。
    /// 当限定L的对角元素为正时，这种分解是唯一的，称为Cholesky分解。
    /// </remarks>
    public abstract class Cholesky<T> : ISolver<T>
        where T : struct, IFormattable, IEquatable<T>
    {
        protected Cholesky(Matrix<T> factor)
        {
            Factor = factor;
        }

        /// <summary>
        /// Cholesky矩阵的下三角矩阵L<br/>
        /// </summary>
        public Matrix<T> Factor { get; private set; }

        /// <summary>
        /// Cholesky矩阵的行列式
        /// </summary>
        public abstract T Determinant { get; }

        /// <summary>
        /// Log(Determinant) 行列式对数
        /// </summary>
        public abstract T DeterminantLn { get; }

        /// <summary>
        /// 计算输入矩阵的Cholesky因式分解。
        /// </summary>
        /// <param name="matrix"></param>
        public abstract void Factorize(Matrix<T> matrix);


        #region ISolver<T>

        public virtual Matrix<T> Solve(Matrix<T> input)
        {
            var x = Matrix<T>.Builder.SameAs(input, input.RowCount, input.ColumnCount, fullyMutable: true);
            Solve(input, x);
            return x;
        }
        public abstract void Solve(Matrix<T> input, Matrix<T> result);


        public virtual Vector<T> Solve(Vector<T> input)
        {
            var x = Vector<T>.Builder.SameAs(input, input.Count);
            Solve(input, x);
            return x;
        }
        public abstract void Solve(Vector<T> input, Vector<T> result);

        #endregion


        //}}@@@
    }



}

